package mammuthus.slave


import akka.actor._
import akka.actor.Actor
import mammuthus.protocal._
import net.csdn.common.logging.Loggers
import mammuthus.protocal.ExecuteShellCommandRequest
import mammuthus.tool.{SystemTool, Tool}
import java.io.File
import mammuthus.docker.protocal.TimeOutResponse


class SlaveActor(slave: Slave) extends Actor with DockerActor {
  val logger = Loggers.getLogger(getClass)

  def dockerClient = slave.dockerClient

  override def receive: Receive = {
    case RegisterAgentSuccess =>
      if (System.currentTimeMillis() % 10 < 3)
        logger.info("slave -> master heartbeat")

    case ExecuteShellCommandRequest(hostName, shellCommand, token, timeout) =>
      logger.info(s"${slave.hostName} execute ExecuteShellCommandRequest shellCommand=$shellCommand token=$token")
      val taskId = try{
        InteractiveShellCommand.startWithTimeout(shellCommand, token, timeout)
      }catch {
        case e:Exception =>
          logger.error(s"$hostName execute ExecuteShellCommandRequest shellCommand=$shellCommand ", e)
          "-"
      }
      sender ! ExecuteShellCommandResponse(ShellTask(taskId, hostName), "")

    case ExecuteBlockShellCommandRequest(ExecuteShellCommandRequest(hostName, shellCommand, token, timeout)) =>
      logger.info(s"${slave.hostName} execute ExecuteBlockShellCommandRequest shellCommand=$shellCommand token=$token")
      val res = try{
        ShellCommand.execWithExitValue(shellCommand, timeout)
      }catch {
        case e:Exception =>
        logger.error(s"$hostName execute ExecuteBlockShellCommandRequest shellCommand=$shellCommand ", e)
        (-1,e.getMessage,"")
      }
      val success = res._1 == 0
      sender ! ExecuteBlockShellCommandResponse(hostName, success, res._2 + "" + res._3)

    case ExecuteDownloadCommandRequest(hostName, url, filePath) =>
      logger.info(s"${slave.hostName} execute ExecuteDownloadCommandRequest url=$url filePath=$filePath")
      val (success, msg) = try {
        Tool.fileDownload.downloadFile(url, filePath)
      } catch {
        case e: Exception =>
          logger.error(s"$hostName execute ExecuteDownloadCommandRequest url=$url filePath=$filePath", e)
          (false, e.getMessage)
      }
      slave.masterRef ! ExecuteDownloadCommandResponse(success, msg, ExecuteDownloadCommandRequest(hostName, url, filePath))

    case BlockExecuteDownloadCommandRequest(hostName, url, filePath) =>
      logger.info(s"${slave.hostName} execute BlockExecuteDownloadCommandRequest url=$url filePath=$filePath")
      val (success, msg) = try {
        Tool.fileDownload.downloadFile(url, filePath)
      } catch {
        case e: Exception =>
          logger.info(s"$hostName execute BlockExecuteDownloadCommandRequest url=$url filePath=$filePath", e)
          (false, e.getMessage)
      }
      sender ! ExecuteDownloadCommandResponse(success, msg, ExecuteDownloadCommandRequest(hostName, url, filePath))

    case ShellProgressTask(ShellTask(taskId, hostName), offset) =>
      logger.info(s"${slave.hostName} execute ShellProgressTask taskId=$taskId offset=$offset")
      val result = try {
        InteractiveShellCommand.progress(taskId, offset)
      }
      catch {
        case e: Exception =>
          logger.info(s"$hostName execute ShellProgressTask taskId=$taskId offset=$offset", e)
          (ShellExecuteStatus(true, false, true), (-1l, e.getMessage))
      }
      sender ! ExecuteShellCommandProgressResponse(ShellTask(taskId, hostName), result._2._1, result._2._2, result._1)

    case WriteFileTask(hostName: String, msg, path, append) =>
      logger.info(s"$hostName execute WriteFileTask path:$path")
      val success = try {
        SystemTool.writeFile(path, msg, append)
      } catch {
        case e: Exception =>
          logger.info(s"$hostName execute WriteFileTask path=$path append=$append msg=$msg ", e)
          (false, e.getMessage)
      }
      sender ! WriteFileTaskResponse(hostName, success._1, success._2)


    case WriteJSONFileTask(hostName, msg: Map[String, String], path) =>
      logger.info(s"$hostName execute WriteFileTask path:$path")
      val success = try {
        SystemTool.writeJSONFile(path, msg)
      } catch {
        case e: Exception =>
          logger.info(s"$hostName execute WriteJSONFileTask $msg", e)
          (false, e.getMessage)
      }
      sender ! WriteFileTaskResponse(hostName, success._1, success._2)


    case ExecuteMammuthusConfStartRequest(servers: String) =>
      logger.info(s"${slave.hostName} execute ExecuteMammuthusConfStartRequest zookeeper servers:$servers")
      slave.mammuthusConf.start(servers)
      sender ! ExecuteMammuthusConfStartResponse

    case AppLogRequest(hostName, filePath, offset, size) =>
      val abc = try {
        ShellCommand.progress(filePath, offset, size)
      } catch {
        case e: Exception =>
          logger.info(s"$hostName execute AppLogRequest path:$filePath offset:$offset size:$size", e)
          (-1l, e.getMessage, 0l)
      }
      sender ! AppLogResponse(hostName, filePath, abc._1, abc._2, abc._3)

    case ListAppLogRequest(hostName, filePath) =>
      val temp = new File(filePath)
      val listFiles = if (!temp.exists() || !temp.isDirectory) List[FileInfo]()
      else temp.listFiles().map {
        f =>
          FileInfo(f.getName, f.isDirectory, f.length(), f.lastModified())
      }.toList
      sender ! ListAppLogResponse(hostName, filePath, listFiles)

    case DockerRequest(item) =>
      logger.info(item.toString)
      import scala.concurrent._
      import scala.concurrent.duration._
      import ExecutionContext.Implicits.global
      val f = future {
        dockerProcess(item)
      }
      val res = try Await.result(f, 14 seconds) catch {
        case e: Exception =>
          TimeOutResponse(e.getMessage)
      }
      sender ! res
  }
}




